
		AREA	|ARM$$code|,CODE,READONLY

		GET	OSLib:OSLib.Hdr.OS

		GET	hdr/cp

		EXPORT	clean_Dcache
		EXPORT	cpu_id
		EXPORT	drain_WB
;		EXPORT	irq_disable
;		EXPORT	irq_restore
;		EXPORT	locate_l1pt
		EXPORT	pld
		EXPORT	plds
;		EXPORT	purge_DTLB
;		EXPORT	read_uh

;		EXPORT	l1pt


cpu_id		MRS	a2,CPSR
		TST	a2,#&0F
		SWIEQ	XOS_EnterOS
		MRC	CP15,0,a1,C0,C0,0
		TST	a2,#&0F
		MSREQ	CPSR_c,a2
		MOV	pc,lr

;--------------------------------------------------------------------------------------------------
;
; DCache cleaning for StrongARM / XScale CPU
;
; NOTE: This intentionally leaves the Icache and ITLB untouched
;
; entry	R0 = 0 for complete address space, 1 if range specified
;	R1,R2 = range if bit 0 of R0 set

clean_Dcache	MRS	R12,CPSR
		TST	R12,#&0F
		SWIEQ	XOS_EnterOS

		TST	R0,#1		;complete clean requested?
		BEQ	sync_complete

		;Would it be quicker to perform a clean all?
		;
;??? THIS COMMENT AND/OR SIZE THRESHOLD NEEDS UPDATING!
		; since the 'clean all' function performs 1024 LDRs
		; and each LDR writes 32 bytes and reads 32 bytes
		; (worst case) this is equivalent to 2048 'clean single entry'
		; operations (again worst case).
		; Therefore, if the address range affected exceeds 64K then
		; cleaning each entry in turn is likely be slower than the
		; _worst case_ performance of the 'clean all' alternative.

		ADD	R2,R2,#31	;round-up
		BIC	R1,R1,#31	;round-down
		BIC	R2,R2,#31
		SUBS	R2,R2,R1
		BLO	sync_return	;upper bound was below lower bound!
		BEQ	sync_single	;single address to be cleaned
		CMP	R2,#65536
		BHS	sync_complete

		;clean Dcache entries for the address range affected

sync_entry_lp	SUBS	R2,R2,#128
		MCRCS	CP15,0,R1,C7,C10,1
		ADDCS	R1,R1,#32
		MCRCS	CP15,0,R1,C7,C10,1
		ADDCS	R1,R1,#32
		MCRCS	CP15,0,R1,C7,C10,1
		ADDCS	R1,R1,#32
		MCRCS	CP15,0,R1,C7,C10,1
		ADDCS	R1,R1,#32
		BHI	sync_entry_lp
		ADDCC	R2,R2,#128

		;tail

		CMP	R2,#96
		MCRHS	CP15,0,R1,C7,C10,1
		ADDHS	R1,R1,#32
		CMPLO	R2,#64
		MCRHS	CP15,0,R1,C7,C10,1
		ADDHS	R1,R1,#32
		CMPLO	R2,#32
sync_single	MCRHS	CP15,0,R1,C7,C10,1
		ADDHS	R1,R1,#32
		B	sync_leave

sync_complete	;perform complete writeback of Dcache contents by
		; reading the first 32K/64K of our application code into
		; the cache (Obviously our module code must be marked
		; as cacheable for this to work. Note that we need
		; to use 32K/64K since the module code could already have
		; been cached by other accesses and reading from it
		; wouldn't necessarily force other data out of the
		; cache)

		MRC	CP15,0,R1,C0,C0,0
		TST	R1,#1<<18		;SA = &4401xxxx, XS = &6905xxxx
		BEQ	sync_comp_rd

		MOV	R2,#&10000000
		ADD	R3,R2,#64*1024

sync_comp_lp	MCR	CP15,0,R2,C7,C5,6
		ADD	R2,R2,#32
		MCR	CP15,0,R2,C7,C5,6
		ADD	R2,R2,#32
		MCR	CP15,0,R2,C7,C5,6
		ADD	R2,R2,#32
		MCR	CP15,0,R2,C7,C5,6
		ADD	R2,R2,#32
		MCR	CP15,0,R2,C7,C5,6
		ADD	R2,R2,#32
		MCR	CP15,0,R2,C7,C5,6
		ADD	R2,R2,#32
		MCR	CP15,0,R2,C7,C5,6
		ADD	R2,R2,#32
		MCR	CP15,0,R2,C7,C5,6
		ADD	R2,R2,#32

		CMP	R2,R3
		BLO	sync_comp_lp

sync_leave	MCR	CP15,0,R0,C7,C10,4	;drain write buffer
sync_return	TST	R12,#&0F
		MSREQ	CPSR_c,R12
		MOV	PC,R14

sync_comp_rd	LDR	R2,=app_base
		ADD	R3,R2,#32*1024
sync_comp_rd_lp	LDR	R1,[R3],#32
		LDR	R1,[R3],#32
		LDR	R1,[R3],#32
		LDR	R1,[R3],#32
		CMP	R2,R3
		BLO	sync_comp_lp

		MCR	CP15,0,R0,C7,C10,4	;drain write buffer
		TST	R12,#&0F
		MSREQ	CPSR_c,R12
		MOV	PC,R14





;purge_DTLB	MCR	CP15,0,R0,C8,C6,0
;		MOV	pc,lr
;

drain_WB	MRS	R1,CPSR
		TST	R1,#&0F
		SWIEQ	XOS_EnterOS
		MCR	CP15,0,R0,C7,C10,4
		TST	R1,#&0F
		MSREQ	CPSR_c,R1
		MOV	pc,lr

pld		PLD	[a1,a2]
		MOV	pc,lr

plds		PLD	[a1]
		PLD	[a2]
		PLD	[a3]
		MOV	pc,lr


;read_uh		LDRH	a1,[a1,a2]
;		MOV	pc,lr


;irq_disable	MRS	R0,CPSR
;		ORR	R1,R0,#&80
;		MSR	CPSR_c,R1
;		MOV	PC,R14

;irq_restore	MSR	CPSR_c,R0
;		MOV	PC,R14


;locate_l1pt	LDR	a4,=l1pt
;		MRC	CP15,0,a1,C2,C0
;		SUB	sp,sp,#12
;		MOV	a3,#1
;		MOV	ip,lr
;		MOV	a2,sp
;		STR	a1,[sp,#8]
;		MOV	a1,#&1400
;		SWI	XOS_Memory
;		LDRVC	a3,[sp,#4]
;		MOVVC	a1,#0
;		ADD	sp,sp,#12
;		STRVC	a3,[a4]
;		MOV	pc,ip

		AREA	|!!!App$Header|,CODE,READONLY
app_base

;		AREA	|ARM$$zidata|,DATA,NOINIT
;
;l1pt		%	4

		END
